package com.hs.jhzd.service.fp;

import com.hs.jhzd.entity.Fingerprint;
import com.hs.jhzd.entity.Jc_rytzmxxb;
import com.hs.jhzd.entity.Police;
import com.hs.jhzd.entity.Prisoner;
import com.hs.jhzd.entity.dto.FingerprintMatcher;
import com.hs.jhzd.repository.*;
import com.hs.jhzd.service.fp.jni.FingerprintZZJNIService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.Callable;

@Service
@Slf4j
public class FingerprintService {
    @Value("${fp.switch}")
    private Boolean needFp;

    @Value("${fp.path}")
    private String fpPath;

    @Value("${fp.image}")
    private Boolean needImage;

    @Value("${jsbh}")
    private String jsbh;

    @Autowired
    private FingerprintRepository fingerprintRepository;

    @Autowired
    private PrisonerRepository prisonerRepository;

    @Autowired
    private PoliceRepository policeRepository;

    @Autowired
    private FingerprintZZJNIService jniPrisonerService;

    @Autowired
    private SwipeRecordRepository swipeRecordRepository;

    @Autowired
    private Jc_rytzmxxbRepository jc_rytzmxxbRepository;

    private CaffeineCache fingerprintCache;

    @Autowired
    private CacheManager cacheManager;
    @Autowired
    private FingerprintZZJNIService fingerprintZZJNIService;

    public void init(String prisonId, String type) {
        // TODO Auto-generated method stub

    }

    @PostConstruct
    private void initCache() {
        fingerprintCache = (CaffeineCache) cacheManager.getCache("fingerprintCache");
        List<Prisoner> prisoners = prisonerRepository.findAll();
        if (CollectionUtils.isEmpty(prisoners)) {
            return;
        }
        for (Prisoner p : prisoners) {
            if (StringUtils.isBlank(p.getJsh())) {
                log.error("【指纹缓存初始化】在押人员{}监舍号为空，指纹无法初始化", p.getName());
                continue;
            }
            List<Fingerprint> fingerprints = fingerprintCache.get(p.getJsh(), List.class);
            if (fingerprints == null) {
                fingerprints = new ArrayList<>();
            }
            List<Fingerprint> prisonerFingerprints = fingerprintRepository.findPrisonerFingerprintByNumber(p.getRybh());
            if (CollectionUtils.isEmpty(prisonerFingerprints)) {
                continue;
            }
            fingerprints.addAll(prisonerFingerprints);
            fingerprintCache.put(p.getJsh(), fingerprints);
        }

        List<Police> polices = policeRepository.findAll();
        if (CollectionUtils.isEmpty(polices)) {
            return;
        }
        for (Police p : polices) {
            List<Jc_rytzmxxb> fingerprints = fingerprintCache.get("police", List.class);
            if (fingerprints == null) {
                fingerprints = new ArrayList<>();
            }
            List<Jc_rytzmxxb> policeFingerprints = jc_rytzmxxbRepository
                    .findByRybh(p.getPoliceId());
            if (CollectionUtils.isEmpty(policeFingerprints)) {
                continue;
            }
            fingerprints.addAll(policeFingerprints);
            fingerprintCache.put("police", fingerprints);
        }
    }

    public List<Fingerprint> getFingerprint2Add(String prisonId, Date lastSynchronizeTime) {
        return fingerprintRepository.getFingerprint2Add(lastSynchronizeTime);
    }

    public List<Prisoner> getPrinsoner2Delete(Date lastSynchronizeTime) {
        return prisonerRepository.getPrinsoner2Delete(lastSynchronizeTime);
    }

    private List<Fingerprint> findByDormCode(String dormCode) {
        List<Fingerprint> fingerprints = new ArrayList<>();
        List<Prisoner> prisoners = prisonerRepository.findByJshAndRybj(dormCode,"3");
        if (CollectionUtils.isEmpty(prisoners)) {
            return Collections.emptyList();
        }
        for (Prisoner p : prisoners) {
            List<Fingerprint> prisonerFingerprints = fingerprintRepository.findPrisonerFingerprintByNumber(p.getRybh());
            if (CollectionUtils.isEmpty(prisonerFingerprints)) {
                continue;
            }
            fingerprints.addAll(prisonerFingerprints);
        }
        return fingerprints;
    }

    public Prisoner findPrisonerByFingerprint(byte[] fingerprint, String dormCode, String prisonId, String string) {
        List<Fingerprint> fingerprints = fingerprintCache.get(dormCode, new Callable<List<Fingerprint>>() {
            @Override
            public List<Fingerprint> call() throws Exception {
                return new ArrayList<>();
            }
        });

        if (CollectionUtils.isEmpty(fingerprints)) {
            fingerprints = findByDormCode(dormCode);
            if (CollectionUtils.isEmpty(fingerprints)) {
                log.error("监室{}没有在押人员指纹！无法比对，返回空", dormCode);
                return null;
            }
            fingerprintCache.put(dormCode, fingerprints);
        }
        FingerprintMatcher maxMatcher = new FingerprintMatcher();
        maxMatcher.setSimliarity(0);
        for (Fingerprint f : fingerprints) {
            if (f.getFeatureBase() == null || f.getFeatureBase().length() < 1) {
                log.error("在押人员{}没有录入指纹，即将跳过，比对下一个在押人员", f.getRybh());
                continue;
            }
            int score = fingerprintZZJNIService.match(Base64.getDecoder().decode(fingerprint), Base64.getDecoder().decode(f.getFeatureBase().getBytes()), 3);
            if (score == 0) {
                score = 100;
            }
            log.debug("在押人员{}比对分数{}", f.getRybh(), score);
            if (score >= 50 && score > maxMatcher.getSimliarity()) {
                maxMatcher.setId(f.getRybh());
                maxMatcher.setFingercode(11);
                maxMatcher.setSimliarity(score);
            }
        }
        if (maxMatcher.getSimliarity() == 0) {
            log.debug("没有比对到在押人员，即将返回空，下一步进行民警比对");
            return null;
        }
        return prisonerRepository.findByRybh(maxMatcher.getId());
    }

    public Police findPoliceByFingerprint(byte[] fingerprint, String prisonId, String dormCode) {
        List<Jc_rytzmxxb> fingerprints = fingerprintCache.get("police", new Callable<List<Jc_rytzmxxb>>() {
            @Override
            public List<Jc_rytzmxxb> call() throws Exception {
                return new ArrayList<>();
            }
        });

        if (CollectionUtils.isEmpty(fingerprints)) {
           fingerprints = jc_rytzmxxbRepository.findAll();
            if (CollectionUtils.isEmpty(fingerprints)) {
                log.error("民警指纹数据不存在，无法比对，即将返回空");
                return null;
            }
            fingerprintCache.put("police", fingerprints);
        }
        FingerprintMatcher maxMatcher = new FingerprintMatcher();
        maxMatcher.setSimliarity(0);
        for (Jc_rytzmxxb f : fingerprints) {
            if (f.getZwtzm() == null || f.getZwtzm().length() < 1) {
                log.error("民警{}得指位{}没有录入指纹，即将跳过，比对下一个民警", f.getRybh());
                continue;
            }

            byte[] bytes = f.getZwtzm().getBytes();
            Base64.getDecoder().decode(fingerprint);
            Base64.getDecoder().decode(f.getZwtzm().getBytes());
            int score = jniPrisonerService.match(Base64.getDecoder().decode(fingerprint), Base64.getDecoder().decode(f.getZwtzm().getBytes()), 0);
            log.debug("民警{}指位{}比对分数{}", f.getRybh(), score);
            if (score == 0) {
                score = 100;
            }
            if (score >= 100 && score > maxMatcher.getSimliarity()) {
                maxMatcher.setId(f.getRybh());
                maxMatcher.setFingercode(11);
                maxMatcher.setSimliarity(score);
                return policeRepository.findByPoliceId(maxMatcher.getId());
            }
        }

        return null;
    }

}
